﻿#include <stdio.h>
#include <stdlib.h>
#include "uv.h"

uv_loop_t loop;
uv_tcp_t server;
sockaddr_in addr;
int nerror;

void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
    // read buffer new
    buf->base = new char[suggested_size];// 建议值一般是65536
    buf->len = suggested_size;
//    fprintf(stdout, "alloc buffer\n");
}

void after_write(uv_write_t *req, int status) {
    if (status) {
        fprintf(stderr, "write error %s\n", uv_strerror(status));
    }
//    delete[] req->data; // read buffer delete
    delete req;
//    fprintf(stdout, "delete buffer\n");
}

char * resp = "HTTP/1.1 200 OK\r\n\
Server: libuv/1.9.3\r\n\
Date: Thu, 13 Aug 2018 03:04:20 GMT\r\n\
Content-Type: text/plain\r\n\
Content-Length: 17\r\n\
Connection: keep-alive\r\n\r\n\
hello_world, xin!";
void after_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
    // 读取完成
//    fprintf(stdout, "request len: %d\n%s\n", nread, buf->base);
    delete[] buf->base; // read buffer delete

    uv_write_t* w_req = new uv_write_t;
    uv_buf_t realBuff = uv_buf_init(resp, strlen(resp));
    w_req->data = (void*)NULL;
    uv_write(w_req, client, &realBuff, 1, after_write);
//    uv_close((uv_handle_t*)client, NULL);
}
void on_new_connection(uv_stream_t* server, int status){
    if( status < 0 ){
        fprintf(stderr, "new connection error, %s\n", uv_strerror(nerror));
        return;
    }
//    fprintf(stdout, "new connection\n");
    uv_tcp_t *c = new uv_tcp_t;
    uv_tcp_init(&loop, c);
    if( uv_accept(server, (uv_stream_t*)c) == 0 ){
        uv_read_start((uv_stream_t*)c, alloc_buffer, after_read);
    }else{
        uv_close((uv_handle_t*)c, NULL);
        delete c;
    }
}

int main(int argc, char* argv[]){
    fprintf(stdout, "tcp server demo\n");
    uv_loop_init(&loop);
    uv_tcp_init(&loop, &server);
    uv_ip4_addr("0.0.0.0", 9090, &addr);
    fprintf(stdout, "bind addr :9090\n");
    nerror = uv_tcp_bind(&server, (const sockaddr*)&addr,0);
    if( nerror == UV__EADDRINUSE ){
        fprintf(stderr,"bind addr 9090 error!\n");
        return 1;
    }
    // tcp等待队列大小为128
    fprintf(stdout, "listen new connection cb...\n");
    nerror = uv_listen((uv_stream_t*)&server, 128, on_new_connection);
    if( nerror ){
        fprintf(stderr,"Listen error, %s\n", uv_strerror(nerror));
        return 1;
    }
    fprintf(stdout, "run\n");
    nerror = uv_run(&loop, UV_RUN_DEFAULT);
    return nerror;
}

